#include "Voronoi.h"

#include <math.h>

void VTesselation::CreateRandomPoints(Terrain* t)
{
	float s = t->GetAbsSize();
	m_numOfPoints=50;
	m_Xvals = new float[m_numOfPoints];
	m_Yvals = new float[m_numOfPoints];
	m_minX=-(s/2);
	m_minY=-(s/2);
	m_maxX=(s/2);
	m_maxY=(s/2);
	for (unsigned int i=0;i<m_numOfPoints;++i)
	{
		float pointx = (fmod((float)std::rand(),s/2)+0.5+fmod((float)std::rand(),s/2))+0.5-(s/2);
		float pointy = (fmod((float)std::rand(),s/2)+0.5+fmod((float)std::rand(),s/2))+0.5-(s/2);

		m_Xvals[i]=pointx;
		m_Yvals[i]=pointy;
		m_vPoints.push_back(D3DXVECTOR2(pointx,pointy));
	}

}
void VTesselation::Divide()
{
	m_Graph.Clear();
	if(m_vPoints.empty())
	{
		printf("Points not generated");
		MessageBox(0,L"VTesselation points need to be created before dividing!",L"Missed something..",MB_OK);
		assert("VTesselation points need to be created before dividing");
	}

    if(!m_Generator.generateVoronoi(m_Xvals,m_Yvals,m_numOfPoints,m_minX,m_maxX,m_minY,m_maxY,/*sqrt(8.0f)+*/0.1))
	{
		MessageBox(0,L"Problem generating Voronoi diagram",L"Damn you Fortune!",MB_OK);
		assert("Problem generating Voronoi diagram");
	}

	m_Generator.resetIterator();
	float x1;
	float y1;
	float x2;
	float y2;
	/*m_vEdges.push_back(LineSeg(D3DXVECTOR2(m_minX,m_minY),D3DXVECTOR2(m_maxX,m_minY)));
	m_vEdges.push_back(LineSeg(D3DXVECTOR2(m_minX,m_minY),D3DXVECTOR2(m_minX,m_maxY)));
	m_vEdges.push_back(LineSeg(D3DXVECTOR2(m_maxX,m_minY),D3DXVECTOR2(m_maxX,m_maxY)));
	m_vEdges.push_back(LineSeg(D3DXVECTOR2(m_minX,m_maxY),D3DXVECTOR2(m_maxX,m_maxY)));*/
	
	
	while(m_Generator.getNext(x1,y1,x2,y2))
	{
		D3DXVECTOR2 vec1 = D3DXVECTOR2(x1,y1);
		D3DXVECTOR2 vec2 = D3DXVECTOR2(x2,y2);

		//pushback into edges
		m_vEdges.push_back(LineSeg(vec1,vec2));


		m_setNodes.insert(vec1);
		m_setNodes.insert(vec2);

		m_mapNodeLinks[vec1].push(vec2);
		m_mapNodeLinks[vec2].push(vec1);

		D3DXVECTOR2 d= vec2-vec1;
		float cost = sqrt((d.x*d.x)+(d.y*d.y));
		int node1= m_Graph.AddNode(GraphNode(vec1));
		int node2= m_Graph.AddNode(GraphNode(vec2));
		m_Graph.AddEdge(GraphEdge(node1,node2,cost));
		
	}
	
	GraphNode BtmLeft = GraphNode(D3DXVECTOR2(m_minX,m_minY));
	GraphNode TopLeft = GraphNode(D3DXVECTOR2(m_minX,m_maxY));
	GraphNode BtmRight = GraphNode(D3DXVECTOR2(m_maxX,m_minY));
	GraphNode TopRight = GraphNode(D3DXVECTOR2(m_maxX,m_maxY));

	
	std::set<GraphNode,GNLess> Top;
	std::set<GraphNode,GNLess> Btm;
	std::set<GraphNode,GNLess> Lft;
	std::set<GraphNode,GNLess> Rgt;

	//if any of the nodes are on the limits they are candidates for the next step
	for (unsigned int i=0; i<m_Graph.GetNumNodes();++i)
	{
		GraphNode* cur = m_Graph.GetNode(i);
		
		if(cur->GetPos().y>m_maxY-0.001)
		{
			Top.insert((*cur));
		}
		if(cur->GetPos().y<m_minY+0.001)
		{
			Btm.insert((*cur));
		}
		if(cur->GetPos().x>m_maxX-0.001)
		{
			Rgt.insert((*cur));
		}
		if(cur->GetPos().x<m_minX+0.001)
		{
			Lft.insert((*cur));
		}
	}

	// add these after looping through the nodes to avoid false positives

	BtmLeft.SetIndex(m_Graph.AddNode(BtmLeft));
	TopLeft.SetIndex(m_Graph.AddNode(TopLeft));
	BtmRight.SetIndex(m_Graph.AddNode(BtmRight));
	TopRight.SetIndex(m_Graph.AddNode(TopRight));


	//in order to attach all the sides together and leave no unfinished polygons, move through the sides of the graph linking them up.
	D3DXVECTOR2 diff;
	float cost;

	//TOP LINE
	GraphNode* Last = &TopLeft;
	for (std::set<GraphNode,GNLess>::iterator it = Top.begin();it!=Top.end();it++)
	{
		diff = Last->GetPos()-(*it).GetPos();
		cost = sqrt((diff.x*diff.x)+(diff.y*diff.y));
		m_Graph.AddEdge(GraphEdge(Last->GetIndex(),(*it).GetIndex(),cost));
		Last=m_Graph.GetNode((*it).GetIndex());
	}
	diff = Last->GetPos()-TopRight.GetPos();
	cost = sqrt((diff.x*diff.x)+(diff.y*diff.y));
	m_Graph.AddEdge(GraphEdge(Last->GetIndex(),TopRight.GetIndex(),cost));

	//BOTTOM LINE
	Last = &BtmLeft;
	for (std::set<GraphNode,GNLess>::iterator it = Btm.begin();it!=Btm.end();it++)
	{
		diff = Last->GetPos()-(*it).GetPos();
		cost = sqrt((diff.x*diff.x)+(diff.y*diff.y));
		m_Graph.AddEdge(GraphEdge(Last->GetIndex(),(*it).GetIndex(),cost));
		Last=m_Graph.GetNode((*it).GetIndex());
	}
	diff = Last->GetPos()-BtmRight.GetPos();
	cost = sqrt((diff.x*diff.x)+(diff.y*diff.y));
	m_Graph.AddEdge(GraphEdge(Last->GetIndex(),BtmRight.GetIndex(),cost));


	//LEFT
	Last = &BtmLeft;
	for (std::set<GraphNode,GNLess>::iterator it = Lft.begin();it!=Lft.end();it++)
	{
		diff = Last->GetPos()-(*it).GetPos();
		cost = sqrt((diff.x*diff.x)+(diff.y*diff.y));
		m_Graph.AddEdge(GraphEdge(Last->GetIndex(),(*it).GetIndex(),cost));
		Last=m_Graph.GetNode((*it).GetIndex());
	}
	diff = Last->GetPos()-TopLeft.GetPos();
	cost = sqrt((diff.x*diff.x)+(diff.y*diff.y));
	m_Graph.AddEdge(GraphEdge(Last->GetIndex(),TopLeft.GetIndex(),cost));


	//RIGHT
	Last = &BtmRight;
	for (std::set<GraphNode,GNLess>::iterator it = Rgt.begin();it!=Rgt.end();it++)
	{
		diff = Last->GetPos()-(*it).GetPos();
		cost = sqrt((diff.x*diff.x)+(diff.y*diff.y));
		m_Graph.AddEdge(GraphEdge(Last->GetIndex(),(*it).GetIndex(),cost));
		Last=m_Graph.GetNode((*it).GetIndex());
	}
	diff = Last->GetPos()-TopRight.GetPos();
	cost = sqrt((diff.x*diff.x)+(diff.y*diff.y));
	m_Graph.AddEdge(GraphEdge(Last->GetIndex(),TopRight.GetIndex(),cost));
}
